package com.bjy.qa.service.functionaltest.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjy.qa.dao.functionaltest.TestResultCaseDao;
import com.bjy.qa.dao.functionaltest.TestResultStepDao;
import com.bjy.qa.dao.functionaltest.TestResultSuiteDao;
import com.bjy.qa.dao.functionaltest.TestSuiteDao;
import com.bjy.qa.dao.manage.ProjectDao;
import com.bjy.qa.dao.project.RobotDao;
import com.bjy.qa.entity.functionaltest.TestResultCase;
import com.bjy.qa.entity.functionaltest.TestResultStep;
import com.bjy.qa.entity.functionaltest.TestResultSuite;
import com.bjy.qa.entity.functionaltest.TestSuite;
import com.bjy.qa.entity.manage.Project;
import com.bjy.qa.entity.project.Robot;
import com.bjy.qa.enumtype.RunStatus;
import com.bjy.qa.exception.MyException;
import com.bjy.qa.service.functionaltest.ITestResultCaseService;
import com.bjy.qa.service.functionaltest.ITestResultSuiteService;
import com.bjy.qa.util.RobotMsgTool;
import com.bjy.qa.util.TimeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class TestResultCaseService extends ServiceImpl<TestResultCaseDao, TestResultCase>  implements ITestResultCaseService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static ConcurrentHashMap<String, Boolean> noticedMap = new ConcurrentHashMap<>(); // 已发送通知锁
    private final static String NOTICED_KEY = "notified-%d-%d-%d"; // 通知 key 占位符

    @Resource
    private RobotMsgTool robotMsgTool;

    @Resource
    TestResultSuiteDao testResultSuiteDao;

    @Resource
    TestResultCaseDao testResultCaseDao;

    @Resource
    TestResultStepDao testResultStepDao;

    @Resource
    ITestResultSuiteService iTestResultSuiteService;

    @Resource
    TestSuiteDao testSuiteDao;

    @Resource
    RobotDao robotDao;

    @Resource
    ProjectDao projectDao;

    @Override
    public  Map<String, TestResultCase> getCaseResultDetails(Long cid, Long rid) {
        Map<String, TestResultCase> retMap = new LinkedHashMap<>();

        // 将测试结果中的数据，按照 ic 分组放入 map 中
        List<TestResultStep> testResultStepList = testResultStepDao.selecByCaseIdAndResultId(rid, cid);
        for (TestResultStep testResultStep : testResultStepList) {
            TestResultCase testResultCase = retMap.get(testResultStep.getIc());
            if (testResultCase != null) {
                if ("status".equalsIgnoreCase(testResultStep.getMsg())) {
                    if (testResultCase.getStatus() == null || testResultCase.getStatus().getValue() < testResultStep.getStatus().getValue()) {
                        testResultCase.setStatus(testResultStep.getStatus().getValue());
                    }
                } else {
                    if (testResultCase.getTestResultSteps() == null) {
                        testResultCase.setTestResultSteps(new ArrayList<>());
                    }
                    testResultCase.getTestResultSteps().add(testResultStep);
                }
            } else {
                List tempList = new ArrayList<>();
                tempList.add(testResultStep);
                testResultCase = new TestResultCase();
                if ("status".equalsIgnoreCase(testResultStep.getMsg())) {
                    testResultCase.setStatus(testResultStep.getStatus().getValue());
                } else {
                    testResultCase.setStatus(RunStatus.RUNNING.getValue());
                    testResultCase.setTestResultSteps(tempList);
                }
                retMap.put(testResultStep.getIc(), testResultCase);
            }
        }

        return retMap;
    }

    @Override
    public List<TestResultCase> getCaseResult(List<Long> cid, Long sid) {
        return testResultCaseDao.getTestResultCaseByCidList(cid,sid);
    }

    @Override
    public TestResultCase getTestResultCase(Long rid, Long cid) {
        return testResultCaseDao.getTestResultCase(rid, cid);
    }

    @Override
    public String handlerResutl(TestResultStep testResultStep) {
        Long resultId = testResultStep.getRid(); // 测试结果 id
        Long testCaseId = testResultStep.getCid(); // 测试用例 id

        testResultStepDao.insert(testResultStep); // 插入测试结果详情表（ft_test_result_step）

        // 如果 msg 为 status，则更新测试用例结果表（ft_test_result_case）
        if ("status".equalsIgnoreCase(testResultStep.getMsg())) {
            TestResultCase testResultCase = getTestResultCase(resultId, testCaseId); // 根据 测试结果id 和 测试用例id 查询 测试用例结果

            if (testResultCase == null) {
                throw new MyException("测试结果处理失败，上报的 rid: " + resultId + " 中没有对应的 cid: " + testCaseId);
            }

            // 如果上报的 测试用例状态 大于 库里的 测试用例状态 更新
            if (testResultCase.getStatus().getValue() < testResultStep.getStatus().getValue()) {
                testResultCase.setStatus(testResultStep.getStatus().getValue());
                testResultCase.setUpdatedAt(testResultStep.getCreatedAt());
                testResultCase.setCreatedAt(null);
                testResultCaseDao.updateById(testResultCase);
            }

            // 拆开 ic 字段，判断当前case是否全部完成。例如：ic = 1-3，表示当前 case 要运行 3 次，当前是第 1 次
            if (testResultStep.getIc().indexOf("-") >= 0) {
                String[] icArr = testResultStep.getIc().split("-");
                if (icArr.length == 2 && !icArr[0].equals(icArr[1])) {
                    return "测试结果处理成功";
                }
            }

            // 套件运行完毕后更新 suite 表
            if (testResultSuiteDao.countRunningTestcase(resultId) == 0) {
                TestResultSuite testResultSuite = iTestResultSuiteService.getResultInfoById(resultId);
                testResultSuite.setEndAt(testResultStep.getCreatedAt());
                testResultSuite.setTotalTime(TimeUtil.getTimeDiff(testResultSuite.getCreatedAt(), testResultStep.getCreatedAt()));
                testResultSuite.setStatus(testResultSuiteDao.getTestResultStatus(resultId));
                testResultSuite.setUpdatedAt(testResultStep.getCreatedAt());
                testResultSuite.setCreatedAt(null);
                iTestResultSuiteService.updateById(testResultSuite);

                // 套件运行结束后，发送机器人消息
                if (testResultSuite.getSuiteId() > 0) { // SuiteId 小于 0 为 debug 下发的套件，所以非 debug 的套件才发送机器人消息
                    TestSuite testSuite = testSuiteDao.selectById(testResultSuite.getSuiteId());
                    Robot robot = robotDao.selectById(testSuite.getRobotId());
                    if (testSuite != null && robot != null && robot.getRobotToken().length() > 0) {
                        Project project = projectDao.selectById(testSuite.getProjectId());
                        String noticedKey = String.format(NOTICED_KEY, project.getCompanyId(), project.getId(), resultId); // 生成通知 key
                        if (noticedMap.get(noticedKey) == null) { // 未发送过通知，发通知
                            noticedMap.put(noticedKey, true); // 向 noticedMap 中添加已发送通知标记

                            String reportUri = String.format("/#/functional_test/result_detail?companyId=%d&projectId=%d&resultId=%d", project.getCompanyId(), project.getId(), resultId);
                            int pass = testResultSuiteDao.countPassedTestcase(resultId);
                            int warn = testResultSuiteDao.countWarnTestcase(resultId);
                            int skip = testResultSuiteDao.countSkippedTestcase(resultId);
                            int fail = testResultSuiteDao.countFailedTestcase(resultId);
                            logger.info("接口测试套件完成，发送测试报告： resultId: {}, suiteName: {}, pass: {}, warn: {}, skip: {}, fail: {}", resultId, testResultSuite.getSuiteName(), pass, warn, skip, fail);
                            robotMsgTool.sendResultFinishReport(robot.getRobotToken(), robot.getRobotSecret(), "接口报告", testResultSuite.getSuiteName(), pass, warn, skip, fail, reportUri, 1);
                        }
                    }
                }
            }
        }

        return "测试结果处理成功";
    }
}
